home *** CD-ROM | disk | FTP | other *** search
- title LPTx : Line Printer Output Capture Routine
- page 66,132
- ;-------------------------------------------------------------
- ;
- ; MAIN PROGRAM Version 3.0
- ;
- ; (C) Copyright 1985 by Mark DiVecchio, All Rights Reserved
- ;
- ; You may use and freely distribute this program for
- ; non-commercial applications.
- ;
- ; Mark C. DiVecchio
- ; 9067 Hillery Drive
- ; San Diego, CA 92126
- ; 619-566-6810
- ;-------------------------------------------------------------
- ; This program intercepts the BIOS interrupt 17, the line printer
- ; interrupt. It will redirect the output of LPT1, LPT2, or LPT3 to a disk
- ; file. All three redirects may be active at the same time.
- ;
- ; This version (3.0) is fully compatible with IBM's PRINT command and
- ; hopefully most other print spoolers. I changed the method by which
- ; LPTX determines if a resident copy of itself is already in memory.
- ;
- ; Calling sequence:
- ; lptx -1 -o <d:[pathname]filename>
- ;
- ; where -1 means redirect LPT1, -2 means redirect LPT2, -3 means redirect
- ; LPT3
- ; This option must appear first
- ;
- ; -o means start the redirect to file speicfied. If rerouting
- ; is already in progress for the selected line printer,
- ; the old file will be closed first.
- ; (If you do not specify -o but you do specify a line printer,
- ; LPTx will use either the last file name that you gave when
- ; you loaded LPTx or will use the file named LPTX1.LST which it
- ; will create in the root directory
- ; on the default drive - where x is 1, 2, or 3.)
- ;
- ; It is not necessary that you specify the complete path name
- ; for the file. LPTx opens and closes the file each time that it
- ; writes out a block. If you change directories, LPTx will
- ; be able to find the file because it save the complete path.
- ;
- ; -c means close the file and send all furthur output directly to the
- ; line printer.
- ;
- ; if neither option is specified, LPTx just displays the program status.
- ;
- ; note: -1, -2, and -3 are mutually exclusive
- ; -o and -c are mutually exclusive
- ;
- ; examples:
- ;
- ; lptx Displays the program status
- ;
- ; lptx ? Displays a HELP screen
- ;
- ; lptx -1 routes LPT1 output to file named
- ; LPTX1.LST on the default drive or the last
- ; named file.
- ;
- ; lptx -o a:\able.xxx routes LPT1 output to file named
- ; or a:\able.xxx. Any open redirection
- ; lptx a:\able.xxx disk file for LPT1 is closed.
- ;
- ; lptx -2 b:xx.lst routes LPT2 output to file named
- ; XX.LST in the default directory
- ; on drive B:. Any open redirection
- ; disk file for LPT2 is closed.
- ;
- ; lptx -3 d:\ab\cd\file.lst redirects LPT3 output to the file named
- ; file.lst in the directory ab\cd on drive
- ; d:.
- ;
- ; lptx -c closes any disk files open for LPT1 and sends
- ; or the output back to the line printer
- ; lptx -1 -c If no rerouting is taking place to LPT1,
- ; this is a NOP. LPT2 and LPT3 are not
- ; affected.
- ;
- ; lptx -2 -c closes any disk file open for LPT2 and
- ; sends the output back to line printer.
- ; if no rerouting is taking place to LPT2,
- ; this is a NOP. LPT1 and LPT3 are not
- ; affected.
- ;
- ; By rerouting LPT2 or LPT3 to a disk file, you can in effect have 2 or 3
- ; printers on your system. LPT1 can be your physical printer and you can
- ; have LPT2 output going to disk. When you redirect LPT2 or LPT3, LPT1 works
- ; normally.
- ;
- ; If you are rerouting to a diskette file, do not remove the diskette
- ; once the rerouting starts. I recommend rerouting to a hard disk or
- ; a RAM disk.
- ;
- ; If LPTx encounters any kind of error during the rerouting, it terminates
- ; operation and sends output back to the line printer. It does not display
- ; anything but beeps the speaker four times. This prevents your currently
- ; running program from possibly getting destroyed.
- ; An error on LPT1 redirect does not shut down LPT2 or LPT3 redirect.
- ;
- ; LPTx captures the int 17h interrupt vector. It may not operate correctly
- ; with other routines what also intercept that vector.
- ;
- ; Problems may occur with print spoolers which also take over the int 17h
- ; vector. You can be sure that LPTX works correctly by running LPTX after
- ; you have run your print spooler. LPTX will be transparent to the print
- ; spooler but your print spooler may not be transparent to LPTX.
- ; LPTX works fine with IBM's PRINT command.
- ;
- ; LPTx also captures the int 24h critical error interrupt vector. This is
- ; done only for the period that LPTx is using the disk. This prevents
- ; the generation of funny error messages in the middle of other programs
- ; that you may be running. (LPTx justs beeps 4 times and clears itself
- ; out of way if a disk error occurs).
- ;
- ; This version of LPTx can redirect all three printers to three different
- ; files with all 3 active at the same time.
- ;
- ; LPTx uses about 7K of memory for the resident data buffers and
- ; interrupt handler.
- ;
- ; If you modify or find any bugs in this program, I would appreciate
- ; it if you would drop me a line with the changes. Use the address
- ; above.
- ;
- if1
- %out Pass 1
- else
- %out Pass 2
- endif
- ;
- ;-----------------------------------------------------------------
- null equ 0
- off equ 0
- on equ 1
- empty equ 0
- cr equ 13
- lf equ 10
- dollar equ '$'
- colon equ ':'
- backslash equ '\'
- blank equ ' '
- dash equ '-'
- dos_call equ 21h
- bufsize equ 200H ;size of DMA buffer
- display_output equ 9 ;for DOS call
- def_drive equ 19h
- create_file equ 3Ch
- open_file equ 3Dh
- close_file equ 3Eh
- write_file equ 40h
- delete_file equ 41h
- lseek_file equ 42h
- def_path equ 47h
- find_file equ 4Eh
- ;-----------------------------------------------------------------
- ;
- ; Macros
- display macro msg
- mov DX,offset msg
- mov AH,display_output
- int dos_call
- endm
- ;
- ;-----------------------------------------------------------------
- ;
- p_block struc
- ;
- ; data structure - these variables are used only in the
- ; memory resident copy of LPTx. BX is set to point to the offset of the
- ; allocation of this structure for the selected LPT
- ;
- active db off ;1 = this LPTx is on, 0 = off
- handle dw null ;handle of disk file used by this LPT
- ;
- ; space for redirection disk file name
- ;
- filen db 'a:\lptx'
- ptr db blank
- db '.lst',null
- db ' '
- db ' '
- ;
- sp_left dw empty ;bytes left in DMA buffer for this LPT
- buffer db bufsize dup(?) ;data buffer for this LPT
- ;
- p_block ends
- ;
- ;
- ;
- ;-----------------------------------------------------------------
- ;
- subttl Main Code
- page
- %out Assembling CODE Segment
- cseg segment para public 'CODE'
- assume CS:cseg,DS:nothing,SS:nothing
- ;
- org 100h
- lptx: jmp l_start
- id dw 03579h ;unique ID for this program
- ;
- ; What follows is three allocations of the Structure p_block
- ; One for each line printer that we can support.
- ; With this, all three line printers have DMA buffers and flag
- ; variables.
- ; BX is used to point to the offset of the allocation currently in use
- ;
- ; Line printer 1
- lpt1 p_block <,,,'1'>
- ;
- ; Line printer 2
- lpt2 p_block <,,,'2'>
- ;
- ; Line printer 3
- lpt3 p_block <,,,'3'>
- ;
- lptxe db 7,7,7,7,dollar ;ring bell four times
- crit_flag db 0 ;set to one if critical error occured
- off_crit dw 0 ;save old critical error address
- seg_crit dw 0
- ;
- dosstk db 0C80H dup(?) ;place to save INT 21H's stack
- stksav dd 0 ;caller's stack EA
- db 64 dup('STACK ')
- stk equ this byte
- ;-----------------------------------------------------------------
- ;
- ; Interrupt handler
- ;
- prt_int:
- cmp DX,0F0Fh ;my flag to detect that LPTX is
- ;already loaded and alive.
- jne reg_call ;This is a regular print call
- jmp ret_ack
- reg_call: ; set up BX
- push BX
- cmp DX,0 ;lpt1?
- jne chk_lpt2 ;no
- mov BX,offset lpt1 ;offset to LPT1
- jmp short bx_set
- chk_lpt2:
- cmp DX,1 ;lpt2?
- jne chk_lpt3 ;no
- mov BX,offset lpt2 ;offset to LPT2
- jmp short bx_set
- chk_lpt3:
- cmp DX,2 ;lpt3?
- jne ill_ptr ;no - bad printer number
- mov BX,offset lpt3 ;offset to LPT3
- bx_set:
- cmp CS:[BX].active,off ;are we active?
- je sleep ;no
- cmp AH,1 ;initialize call?
- je do_nix ;yes
- cmp AH,2 ;status call?
- je do_nix ;yes
- cmp AH,0 ;print call?
- jne do_nix ;no
- jmp prt_it ;we are active
- do_nix: mov AH,90h ;Ready Status
- pop BX
- iret
- ;
- ill_ptr:mov AH,0
- pop BX
- iret ;return with error status
- ;
- ret_ack: ;return acknowledgement that I'm here
- mov DX,05555h
- mov AX,0AAAAh
- push CS ;now set up ES to point to the resident
- pop ES ; data area
- iret
- ;
- sleep: pop BX ;restore BX before we go to sleep
- db 0EAh ;jump immediate to next handler
- oldint dd ;address of old int 17 routine
- ;-----------------------------------------------------------------
- ;
- ; Start the print process
- ;
- prt_it: push AX
- push BX
- push CX
- push DX
- push DS
- push ES
- push SI
- push DI
- push BP
- ; DS is used as the segment register
- ; for all data during the interrupt
- ;
- push CS
- pop DS ;set up DS
- ;
- cli
- mov SI,SS
- mov word ptr stksav+2,SI ;save caller's stack
- mov SI,SP
- mov word ptr stksav,SI
- mov SI,CS
- mov SS,SI ;give me new bigger stack
- mov SI,offset stk
- mov SP,SI
- sti
-
- call prnt ;print the character
- ;
- cli
- mov SI,word ptr stksav
- mov SP,SI ;restore caller's stack
- mov SI,word ptr stksav+2
- mov SS,SI
- sti
- ;
- pop BP
- pop DI
- pop SI
- pop ES
- pop DS
- pop DX
- pop CX
- pop BX
- pop AX
- jmp do_nix
- ;-----------------------------------------------------------------
- ;
- ; Critical Error Handler
- ;
- crit_int: ;got critical error
- mov CS:crit_flag,on ; set flag
- mov AL,0 ;tells DOS to ignore the
- iret ;error
- ;-----------------------------------------------------------------
- ;
- ; Print a character in AL
- ;
- prnt proc near
- cmp DS:[BX].active,off
- je prtext ;nothing there?
- push AX
- cmp DS:[BX].sp_left,bufsize ;buffer full
- jne intadd ;no
- call flush ;yes, flush buffer
- intadd: pop AX
- mov DI,BX ;offset of this printer's allocation
- add DI,offset buffer ;add in offset of buffer
- add DI,DS:[BX].sp_left ;add in current byte count
- mov DS:[DI],AL ;stuff it
- inc DS:[BX].sp_left
- prtext: ret ;done
- prnt endp
- ;
- ; Flush print buffer to disk file
- ;
- flush proc near
- cmp DS:[BX].sp_left,empty ;buffer non-empty?
- jne flush_buf ;empty, skip it
- ret ;exit
- flush_buf:
- mov DS:[BX].sp_left,empty ;else, reset it
- ;
- push ES
- push DS
- ;
- ; Preserve a chunk of DOS 2.0 across int 21h
- ; See PC Technical reference manual page D-7 for hint.
- ; It comments that only DOS calls 0 - 12 can be safely made
- ; from an interrupt handler. "Use of any other call will
- ; destroy the DOS stack and will leave DOS in an
- ; unpredictable state." What we do here is save and restore
- ; 3200 bytes of the DOS stack and restore it later. We only
- ; do it for the DOS stack. If this was invoked by a user
- ; program, we won't save the DOS stack or the user stack.
- ; It is not necessary.
- ;
- mov AX,word ptr DS:stksav+2 ;get callers stack segment
- cmp AX,0100h ; is it DOS?
- ja flusha ;no, don;t bother to save it
- mov AX,DS ;copy to my segment
- mov ES,AX
- mov AX,word ptr DS:stksav+2 ;copying from caller's stack
- mov DS,AX
- mov SI,0 ;offset into DOS's stack
- mov DI,offset dosstk
- mov CX,0C80h ;length to save
- cld
- rep movsb ;copy DOS's stack
- ;
- pop DS
- push DS
- ;
- flusha:
- ;
- push AX ;save the character
- push BX
- push ES
- mov AX,3524h ;get old critical error vector
- int dos_call
- mov DS:off_crit,BX
- mov DS:seg_crit,ES
- mov DX,offset crit_int
- mov AX,2524h
- int dos_call ;trap critical error vector
- mov DS:crit_flag,off ;clear critical error flag
- pop ES
- pop BX
- pop AX
- ; open file
- mov DX,BX
- add DX,offset filen ;filename
- mov AL,1 ;open for writing
- mov AH,open_file
- int dos_call
- mov DS:[BX].handle,AX ;file handle
- jc flush_err ;error
- cmp DS:crit_flag,on ;critical error?
- je flush_err ;yes
- ;
- push BX
- mov AH,lseek_file
- mov AL,2 ;end of file
- mov CX,0 ;offset 0
- mov DX,0
- mov BX,DS:[BX].handle
- int dos_call
- pop BX
- jc flush_err ;some seek error
- cmp DS:crit_flag,on ;critical error?
- je flush_err ;yes
- ;
- mov CX,bufsize ;buffer length
- mov DX,BX ;offset of structure allocation
- add DX,offset buffer ;add offset of buffer within the
- ; allocation
- push BX
- mov AH,write_file
- mov BX,DS:[BX].handle ;file handle
- int dos_call ;buffer address is DS:DX
- pop BX
- jnc flush_ok
- cmp DS:crit_flag,on ;critical error?
- je flush_err ;yes
- cmp AX,bufsize ;did DOS write it all?
- je flush_ok ;yes
- ;
- flush_err:
- display lptxe ;ring bell
- mov DS:[BX].active,off ;turn us off
- mov DS:crit_flag,off ;clear error flag
- ; ;then try to close the file
- ; ;to save what we can
- flush_ok:
- push BX
- mov BX,DS:[BX].handle
- mov AH,close_file ;close the file
- int dos_call
- pop BX
- ;
- flush_exit:
- pop DS
- pop ES
- ;
- push DS
- lds DX,dword ptr DS:off_crit
- mov AX,2524h ;restore critical error vector
- int dos_call
- pop DS
- ;
- mov AX,word ptr DS:stksav+2 ;copying to DOS's workarea
- cmp AX,100H
- ja flushe ;must be DOS's segment
- push ES
- mov ES,AX
- mov DI,0 ;restore data areas
- mov SI,offset dosstk
- mov CX,0C80H ;length to restore
- cld
- rep movsb ;copy DOS's stack
- pop ES ;restore ES
- ;
- flushe: ret
- flush endp
- ;
- end_res db 0
- ;
- ;
- ; This is the end of the memory resident portion of LPTx
- ;
- ;
- ;--------------------------------------------------------------------
- ;--------------------------------------------------------------------
- ;--------------------------------------------------------------------
- ;
- ; all following data is in the Code Segment
- ;
- mach_type db 0
- save_psp dw 0
- DOS_version db 0 ;Major Version Number
- db 0 ;Minor Version Number
- drive db 0 ;default drive number 0=A etc.
- flag_27 db 0 ; 1=make this copy resident
- wrong_dos db 'DOS 2.0 or later required for LPTx',lf,cr,dollar
-
- up_msg db 'LPTx - Line Printer Redirection Program - V3.00'
- db lf,cr,' Copyright 1985 Mark C. DiVecchio',lf,cr
- db dollar
- resident db lf,cr,'Resident Portion of LPTx Loaded',lf,lf,cr
- db dollar
- lptx_err_3 db 'Could not delete file',lf,cr,dollar
- lptx_over db cr,lf,'File already exists. Do you want to overwrite '
- db 'it? (y or n) :$'
- lptx_nc db 'File selection canceled',cr,lf,dollar
- lptx_del db 'File is being overwritten',lf,cr,dollar
- lptx_cr db lf,cr,dollar
- lptx_bad db 'Invalid Option',lf,cr
- db 'Calling sequence:',lf,cr
- db 'lptx {-1,-2,-3} {-c -o <d:[pathname]filename>}'
- db lf,cr,dollar
- lptx_on db lf,cr,'Redirection started. Disk file opened.'
- db lf,cr,dollar
- lptx_off db lf,cr,'Redirection ended. Disk file closed.'
- db lf,cr,dollar
- lptx_creat db 'Could not create the disk file',lf,cr,dollar
- ;
- ; HELP screen
- ;
- help_msg db lf,cr,'Calling sequence : ',lf,lf,cr
- db 'LPTX -p -f <[d:][\pathname\pathname]filename>'
- db lf,lf,cr
- db ' where p = printer number : 1, 2, or 3',lf,cr
- db ' f = function : o for open a print file'
- db lf,cr
- db ' c for close a print file'
- db lf,cr
- db ' drive letter & pathname are optional'
- db lf,cr
- db ' defaults : p = 1',lf,cr
- db ' f = o',lf,cr,dollar
- ;
- ; messages for STAT proc
- ;
- stat_stat db cr,lf,'LPTx Status :',cr,lf,dollar
- stat_lp db 'lpt'
- stat_ptr db ' : $'
- stat_off db ' not redirected',cr,lf,dollar
- stat_dir db ' redirected to disk file '
- stat_fn db 60 dup (blank)
- ;
- ;
- yn_max db 2 ;max # of char
- yn_act db 0
- yn_in db 2 dup (0)
- ;
- ;--------------------------------------------------------------------
- ;
- ; This is the main routine which is executed each time that LPTx is
- ; called. In this routine, DS points to the data segment which is
- ; transient. ES points to the data segment which is permanently
- ; resident. ES:BX points to the data structure for the selected
- ; line printer, 1, 2, or 3.
- ; The offsets are the same for both. If this is the first
- ; time that LPTx is run, then ES=DS.
- ;
- l_start:
- sti ;interrupts on
- push DS ;Save DS
- xor AX,AX ;clear AX for return IP
- push AX ;put 0 on stack
- ;
- ;to check for machine type look at
- ; F000:FFFE
- ; = FF IBM PC
- ; = FE IBM XT
- ; = FD IBM PCjr
- ; = FC IBM PC AT
- ;
- mov AX,0F000h
- mov ES,AX
- mov BX,0FFFEh
- mov CL,ES:[BX] ;get machine type
- mov mach_type,CL ;save machine type
- mov save_psp,DS ;segment address of PSP
- ;
- ; get the DOS version number
- ; returns zero for pre DOS 2.0 releases
- mov AH,30h
- int dos_call ;call DOS
- mov word ptr DOS_version,AX
- ;
- cmp DOS_version,2 ;is it DOS 2.+
- jge dos_ok ;yes
- display wrong_dos ;print error message
- mov AH,0
- int dos_call ;terminate
- dos_ok:
- ;
- mov AH,def_drive ;get current default drive
- int dos_call
- mov drive,AL ;save the drive number
- display up_msg ;print program ID
- ;
- ; get old interrupt handler
- ;
- mov flag_27,off ;to not make resident
- mov AL,17h ;get current vector address
- mov AH,35h
- int dos_call
- mov word ptr oldint,BX
- mov word ptr oldint[2],ES ;save it for later use
- ;
- ; are we already resident in memory?
- ;
- mov DX,0F0Fh ;check if LPTX is already resident
- mov AX,2 ;get status
- int 17h ;call int 17h - BIOS
- cmp DX,5555h ;my handler sets DX to 5555h
- ;and sets ES
- je in_core ;yes - ES has segment address
- mov flag_27,on ;to make this copy resident
- push CS
- pop ES ;set ES to CS for segment address
- ;
- mov AL,drive
- add AL,'a' ;make it a letter
- mov BX,offset lpt1
- mov ES:[BX].filen,AL ;put it into the filename
- mov BX,offset lpt2
- mov ES:[BX].filen,AL ;put it into the filename
- mov BX,offset lpt3
- mov ES:[BX].filen,AL ;put it into the filename
- in_core: ;ES is ok
- ; ----------------------------------------------------
- ; ES now points to resident data area
- ;
- ; set up ES:BX to point to default data structure
- ;
- mov BX,offset lpt1 ;offset - default to LPT1
- ;
- ;get options and file name
- ;scan input line for line printer number
- ;
- mov SI,81h ;starting offset
- mov CL,DS:80h ;length of input line
- mov CH,0
- cmp CX,0 ;nothing?
- jne inp_lp ;no
- jmp nor_exit ;yes, then just display status
- inp_lp:
- cmp byte ptr DS:[SI],'?' ;a ? ?
- jne cont_scan ;no
- jmp help ;yes - go show help data
- cont_scan:
- cmp byte ptr DS:[SI],dash ;a dash ?
- je got_opt ;yes
- cmp byte ptr DS:[SI],cr ;a carriage return?
- je scan_done ;yes
- cmp byte ptr DS:[SI],blank ;a blank?
- je inp_ret ;yes
- jmp no_b ;assume that we got a file name
- ;without the -o option
- inp_ret:
- inc SI ;ignore blanks
- loop inp_lp ;continue to scan
- ;
- ; scan of whole line is complete, if options were not found, we
- ; use defaults : LPT1 and file LPTX1.LST on the default drive.
- ; note : at least one option must be specified
- ;
- scan_done:
- jmp lptx_make ;go create the file
- ;
- got_opt: ;we got an option
- inc SI ;to option
- cmp byte ptr DS:[SI],'1' ;LPT1?
- jne chk_2
- mov BX,offset lpt1 ;offset from ES
- jmp short inp_ret
- chk_2: cmp byte ptr DS:[SI],'2' ;LPT2?
- jne chk_3
- mov BX,offset lpt2 ;offset from ES
- jmp short inp_ret
- chk_3: cmp byte ptr DS:[SI],'3' ;LPT3?
- jne chk_fil
- mov BX,offset lpt3 ;offset from ES
- jmp short inp_ret
- chk_fil: ;is it file?
- cmp byte ptr DS:[SI],'o' ;open a file
- je file_op ;yes
- cmp byte ptr DS:[SI],'c' ;close a file
- je file_cl ;yes
- display lptx_bad ;incorrect option
- jmp nor_ex
- ;
- file_cl: ;close the output file
- cmp ES:[BX].active,on ;are we active?
- jne no_close ;no
- mov AL,1AH ;CTRL-Z
- mov word ptr ES:stksav+2,AX ;do this so that prnt does
- ;not bother to save the DOS stack
- push DS
- push ES
- pop DS ;set DS to point to resident
- ;data segment
- call prnt ;print end of file mark
- call flush ;flush out write buffer
- pop DS ;restore DS
- ;
- mov ES:[BX].active,off ;make us inactive
- display lptx_off ;redirection off message
- no_close:
- jmp nor_exit ;nothing to close so exit
- file_op: ;open a file for output
- ;get the file name
- inc SI ;to next chracter
- cmp byte ptr DS:[SI],blank ;a blank?
- jne no_b ;no
- inc SI ;skip over blank
- no_b:
- ; at this point, we have found a new file name. We close the old
- ; file if one was open
- cmp ES:[BX].active,on ;are we active?
- jne no_cl ;no
- mov AL,1AH ;CTRL-Z
- mov word ptr ES:stksav+2,AX ;do this so that prnt does
- ;not bother to save the DOS stack
- push DS
- push ES
- pop DS ;set DS to point to resident
- ;data segment
- call prnt ;print end of file mark
- call flush ;flush out write buffer
- pop DS ;restore DS
- ;
- mov ES:[BX].active,off ;make us inactive
- display lptx_off ;redirection off message
- no_cl:
- mov DI,BX ;base of structure
- add DI,offset filen ;add offset of destination
- ;
- push SI ;save pointer to file name
- ; search for a drive letter
- inc SI ;should point to a colon if
- ;one is there
- cmp byte ptr [SI],colon ;?
- je got_drive ;yes
- get_drive:
- mov AL,drive ;get drive letter
- add AL,'a' ;make it a letter
- mov ES:[DI],AL ;put it in file name
- inc DI
- mov byte ptr ES:[DI],colon ;put in a colon
- inc DI
- jmp path_search
- got_drive:
- pop SI ;move pointer back to start
- mov AL,[SI] ;get the given drive
- mov ES:[DI],AL ;move it
- sub AL,'a' ;make it a number
- mov drive,AL ;save the drive number
- inc SI
- inc DI
- mov byte ptr ES:[DI],colon
- inc DI
- inc SI
- push SI ;save new start pointer
- path_search:
- ; now search for a backslash which says that a pathname was given
- bk_s_lp:cmp byte ptr [SI],backslash
- je got_path ;a path
- cmp byte ptr [SI],cr ;end of the file name?
- je get_path ;yes with no path
- inc SI
- jmp short bk_s_lp ;loop
- get_path:
- mov byte ptr ES:[DI],backslash ;create the path
- inc DI
- mov DL,drive ;the current drive
- inc DL ;bump it for DOS
- push DS
- push ES
- pop DS ;set up DS for DOS
- mov SI,DI ;set up SI for pathname
- mov AH,def_path ;get current directory
- int dos_call ;path goes into DS:SI
- pop DS ;restore DS
- cmp byte ptr ES:[SI],null ;null path?
- je null_path ;yes - root directory
- path_lp: ;now find the end of the string
- cmp byte ptr ES:[SI],null ;null byte marks end of pathname
- je end_path ;now append the file name
- inc SI
- jmp short path_lp
- end_path:
- mov byte ptr ES:[SI],backslash
- inc SI
- null_path:
- mov DI,SI ;DI is destination
- got_path:
- pop SI ;restore source of filename
- ; pick up everything to next blank
- get_lp:
- mov AL,DS:[SI] ;character
- mov ES:[DI],AL ;put it away
- cmp AL,cr ;was it a Carriage Return?
- je end_line
- cmp AL,blank ;was it a space?
- je end_line
- inc SI
- inc DI
- jmp short get_lp ;no so get next character
- end_line:
- mov byte ptr ES:[DI],null ;zero out the CR or blank
- ;at the end of the filename
- ;it becomes an ASCIIZ string
- sub DI,BX ;now take out the base and
- cmp DI,offset filen ; make sure that we got something
- jne lptx_make ;file name was ok
- display lptx_creat ;could not understand the file name
- jmp nor_exit ;don't stay resident
- ;
- nor_ex: jmp nor_exit
-
- lptx_make:
- ;
- ; default DTA used by Find File is set by DOS to an offset of
- ; 80h into this program's Program Segment Prefix
- ;
- push DS
- push ES
- pop DS ;uses DS:DX
- mov DX,BX
- add DX,offset filen ;file name
- mov AH,find_file
- mov CX,0 ;normal files only
- int dos_call ;find first match
- pop DS
- jnc lptx_d ;file was found
- jmp lptx_create ;not there - which is ok
- ;file already exists
- lptx_d: display lptx_over
- mov DX,offset yn_max;input buffer
- mov AH,0AH
- int dos_call
- cmp yn_act,0 ;anything typed?
- display lptx_cr
- je lptx_x ;no - exit
- cmp yn_in,'y' ;a yes?
- je lptx_d_yes ;yes
- cmp yn_in,'Y' ;a yes?
- je lptx_d_yes ;yes
- lptx_x: display lptx_nc
- jmp nor_exit ;all done if we can't overwrite
- ;see if we should abort the host
- lptx_d_yes:
- display lptx_del
- ;
- push DS
- push ES
- pop DS ;uses DS:DX
- mov DX,BX
- add DX,offset filen ;file name
- mov AH,delete_file
- int dos_call ;delete file
- pop DS
- jnc lptx_create ;ok its gone
- display lptx_err_3 ;can't delete it
- jmp nor_exit
- ;
- ;
- lptx_create:
- ;
- ; create the file
- push DS
- push ES
- pop DS ;uses DS:DX
- mov DX,BX ;base of this LPT's structure
- add DX,offset filen ;file name
- mov AH,create_file
- mov CX,0 ;normal files only
- int dos_call ;find first match
- pop DS
- jnc creat_ok
- display lptx_creat ;could not create the file
- jmp nor_exit ;don't stay resident
- ;
- creat_ok: ;now close the file
- push BX
- mov BX,AX ;AX was loaded by the create file
- ; call
- mov AH,close_file ;close the file
- int dos_call
- pop BX
- ;
- display lptx_on
- ; set the program up for writing
- mov ES:[BX].sp_left,empty ;set buffer empty
- mov ES:[BX].active,on ;set us on
- ;
- cmp flag_27,on ;make this one resident?
- jne nor_exit ;no
- ;
- ; Now set LPTX up as the new int 17h interrupt handler
- ;
- mov AH,25h ;set interrupt vector
- mov AL,17h ;BIOS printer
- mov DX,offset prt_int
- int dos_call
- display resident ;resident loaded message
- call stat ;display status
- mov DX,offset end_res
- int 27h ;terminate but stay resident
- ;
- ; HELP printer
- ;
- help: display help_msg ;display the HELP screen
- jmp short nor_exit
- ;
- ; Normal exit for transient copy of LPTX
- ;
- nor_exit:
- call stat ;display status
- mov AH,0
- int dos_call ;terminate
- ;------------------------------------------------------------------------
- ;
- ; displays the status of each of the three line printers
- ;
- stat proc near
- ; display each LPTx with a message "not redirected"
- ; or redirected to <filename>
- display stat_stat
- stat_1:
- mov BX,offset lpt1 ;first printer
- mov stat_ptr,'1'
- display stat_lp
- cmp ES:[BX].active,on ;are we active?
- je stat_1_a ;yes
- display stat_off
- jmp short stat_2
- stat_1_a:
- mov SI,BX ;base
- add SI,offset filen ;offset
- mov DI,offset stat_fn
- stat_1_lp:
- mov AL,ES:[SI]
- mov [DI],AL
- inc SI
- inc DI
- cmp AL,null ;loop till a null byte is found
- jne stat_1_lp
- mov byte ptr [DI],cr
- inc DI
- mov byte ptr [DI],lf
- inc DI
- mov byte ptr [DI],dollar
- display stat_dir ;display file name
- ;
- stat_2:
- mov BX,offset lpt2 ;second printer
- mov stat_ptr,'2'
- display stat_lp
- cmp ES:[BX].active,on ;are we active?
- je stat_2_a ;yes
- display stat_off
- jmp short stat_3
- stat_2_a:
- mov SI,BX ;base
- add SI,offset filen ;offset
- mov DI,offset stat_fn
- stat_2_lp:
- mov AL,ES:[SI]
- mov [DI],AL
- inc SI
- inc DI
- cmp AL,null ;loop till a null byte is found
- jne stat_2_lp
- mov byte ptr [DI],cr
- inc DI
- mov byte ptr [DI],lf
- inc DI
- mov byte ptr [DI],dollar
- display stat_dir ;display file name
- ;
- stat_3:
- mov BX,offset lpt3 ;third printer
- mov stat_ptr,'3'
- display stat_lp
- cmp ES:[BX].active,on ;are we active?
- je stat_3_a ;yes
- display stat_off
- jmp short stat_done
- stat_3_a:
- mov SI,BX ;base
- add SI,offset filen ;offset
- mov DI,offset stat_fn
- stat_3_lp:
- mov AL,ES:[SI]
- mov [DI],AL
- inc SI
- inc DI
- cmp AL,null ;loop till a null byte is found
- jne stat_3_lp
- mov byte ptr [DI],cr
- inc DI
- mov byte ptr [DI],lf
- inc DI
- mov byte ptr [DI],dollar
- display stat_dir ;display file name
- ;
- stat_done:
- ret
- stat endp
- ;
- cseg ends
- %out EOF
- end lptx